<xsl:stylesheet version="1.1"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:math="http://exslt.org/math"
	xmlns="http://www.w3.org/2000/svg" 
	extension-element-prefixes="math">
	
	<xsl:param name="obliqueSkewY">26.565</xsl:param>
	<xsl:param name="obliqueScaleX">0.8944</xsl:param>
	<xsl:param name="complimentSkewY"><xsl:value-of select="$obliqueSkewY"/></xsl:param>
	<xsl:param name="complimentScaleX"><xsl:value-of select="$obliqueScaleX"/></xsl:param>
	
	<xsl:param name="degrees-to-radians"><xsl:value-of select="math:constant('PI',12) div 180"/></xsl:param> 

	
	<xsl:template 
		match="part"
		mode="get-max-child-extent">
		<xsl:param name="index">1</xsl:param>
		<xsl:param name="count"><xsl:value-of select="count(part)"/></xsl:param>
		<xsl:param name="parent-angle">0</xsl:param>
		<xsl:param name="max-extent">0</xsl:param>
		<xsl:param name="direction"/>
		<xsl:param name="state"/>
		<xsl:param name="orientation"/>
		<xsl:choose>
			<xsl:when test="$count >= $index">
				<xsl:variable name="new-extent">
					<xsl:apply-templates select="part[position()=$index]" mode="get-extent">
						<xsl:with-param name="parent-angle" select="$parent-angle"/>
						<xsl:with-param name="direction" select="$direction"/>
						<xsl:with-param name="state" select="$state"/>
						<xsl:with-param name="orientation" select="$orientation"/>
					</xsl:apply-templates>
				</xsl:variable>
				
				<xsl:variable name="new-max-extent">
					<xsl:choose>
						<xsl:when test="$direction='north' or $direction='west'">
							<xsl:choose>
								<xsl:when test="$max-extent > $new-extent">
									<xsl:value-of select="$new-extent"/>
								</xsl:when>
								<xsl:otherwise>
									<xsl:value-of select="$max-extent"/>
								</xsl:otherwise>
							</xsl:choose>
						</xsl:when>
						<xsl:otherwise>
							<!-- greater-than comparison -->
							<xsl:choose>
								<xsl:when test="$new-extent > $max-extent">
									<xsl:value-of select="$new-extent"/>
								</xsl:when>
								<xsl:otherwise>
									<xsl:value-of select="$max-extent"/>
								</xsl:otherwise>
							</xsl:choose>
						</xsl:otherwise>
					</xsl:choose>				
				</xsl:variable>
				<xsl:apply-templates select="." mode="get-max-child-extent">
					<xsl:with-param name="direction" select="$direction"/>
					<xsl:with-param name="index" select="$index + 1"/>
					<xsl:with-param name="count" select="$count"/>
					<xsl:with-param name="max-extent" select="$new-max-extent"/>
					<xsl:with-param name="parent-angle" select="$parent-angle"/>
					<xsl:with-param name="state" select="$state"/>
					<xsl:with-param name="orientation" select="$orientation"/>
				</xsl:apply-templates>
			</xsl:when>
			<xsl:otherwise>
			
				<xsl:value-of select="$max-extent"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template match="part" mode="get-extent-of-socketed-length">
		<xsl:param name="direction"/>
		<xsl:param name="state"/>
		<xsl:param name="orientation"/>
		<xsl:param name="rotation">0</xsl:param>
		<xsl:param name="default">0</xsl:param>
		<xsl:param name="mult">1</xsl:param>
		<xsl:param name="socket">joint</xsl:param>

		<xsl:variable name="child-grab">
			<xsl:choose>
				<xsl:when test="part[@socket=$socket]">
					<xsl:apply-templates select="part[@socket=$socket]" mode="get-extent">
						<xsl:with-param name="direction" select="$direction"/>
						<xsl:with-param name="rotation" select="$rotation"/>
						<xsl:with-param name="state" select="$state"/>
						<xsl:with-param name="orientation" select="$orientation"/>
					</xsl:apply-templates>
				</xsl:when>
				<xsl:otherwise>0</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		
		<xsl:variable name="length">
			<xsl:call-template name="get-value">
				<xsl:with-param name="default" select="$default"/>
				<xsl:with-param name="partNode" select="."/>
				<xsl:with-param name="key">length</xsl:with-param>
				<xsl:with-param name="mult" select="$mult"/>
			</xsl:call-template>
		</xsl:variable>
		
		<xsl:choose>
			<xsl:when test="$direction='grabx'">
				<xsl:value-of select="math:cos($rotation * $degrees-to-radians) * $length + $child-grab"/>
			</xsl:when>
			<xsl:when test="$direction='graby'">
				<xsl:value-of select="math:sin($rotation * $degrees-to-radians) * $length + $child-grab"/>				
			</xsl:when>
			<xsl:otherwise>
		
				<xsl:variable name="child-extent">
					<xsl:choose>
						<xsl:when test="part[@socket='joint']">
							<xsl:apply-templates select="part[@socket='joint']" mode="get-extent">
								<xsl:with-param name="state" select="$state"/>
								<xsl:with-param name="orientation" select="$orientation"/>
							</xsl:apply-templates>
						</xsl:when>
						<xsl:otherwise>0</xsl:otherwise>
					</xsl:choose>
				</xsl:variable>
				
				<!-- TODO use direction -->
				<xsl:value-of select="$length + $child-extent"/>
			
			</xsl:otherwise>
		</xsl:choose>

	</xsl:template>	
	
	<!-- skewing in the orientation direction -->
	<xsl:template name="render-skewed">
		<xsl:param name="orientation"/>
		<xsl:param name="state"/>
		<xsl:param name="rotation">0</xsl:param>
		<xsl:param name="part"/>
		<xsl:variable name="skewYAngle">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='southWest'">
					<xsl:value-of select="-$obliqueSkewY"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$obliqueSkewY"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="face">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='northWest'">back</xsl:when>
				<xsl:otherwise>front</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="scaleX">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='southEast'">
					<xsl:value-of select="$obliqueScaleX"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="-$obliqueScaleX"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<g transform="skewY({$skewYAngle}) scale({$scaleX},1) rotate({$rotation})">
			<xsl:apply-templates select="$part" mode="render-skewed-part">
				<xsl:with-param name="state" select="$state"/>
				<xsl:with-param name="face" select="$face"/>
				<xsl:with-param name="skewYAngle" select="$skewYAngle"/>
				<xsl:with-param name="scaleX" select="$scaleX"/>
				<xsl:with-param name="orientation" select="$orientation"/>
			</xsl:apply-templates>
		</g>
	</xsl:template>	
	
	<!-- skewing 90 degrees to orientation angle -->
	<xsl:template name="render-skewed-compliment">
		<xsl:param name="orientation"/>
		<xsl:param name="state"/>
		<xsl:param name="part"/>
		<xsl:param name="rotation">0</xsl:param>
		
		
		<xsl:variable name="skewYAngle">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='southWest'">
					<xsl:value-of select="$complimentSkewY"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="-$complimentSkewY"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="scaleX">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='southWest'">
					<xsl:value-of select="-$complimentScaleX"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$complimentScaleX"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="face">
			<xsl:choose>
				<xsl:when test="$orientation='northEast' or $orientation='northWest'">back</xsl:when>
				<xsl:otherwise>front</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<g transform="skewY({$skewYAngle}) scale({$scaleX},1) rotate({$rotation})">
			<xsl:apply-templates select="$part" mode="render-skewed-part">
				<xsl:with-param name="state" select="$state"/>
				<xsl:with-param name="face" select="$face"/>
				<xsl:with-param name="skewYAngle" select="$skewYAngle"/>
				<xsl:with-param name="scaleX" select="$scaleX"/>
				<xsl:with-param name="orientation" select="$orientation"/>
			</xsl:apply-templates>
		</g>
	</xsl:template>
		
	<!-- gets a description value from a part -->
	<xsl:template name="get-value">
		<xsl:param name="default"/>
		<xsl:param name="partNode"/>
		<xsl:param name="key"/>
		<xsl:param name="mult"/>
		<xsl:variable name="result">
			<xsl:choose>
				<xsl:when test="$partNode/description[@key=$key]">
					<xsl:value-of select="$partNode/description[@key=$key]/@value"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$default"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:choose>
			<xsl:when test="$mult">
				<xsl:value-of select="$mult * $result"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$result"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>		
	
</xsl:stylesheet>